home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d17 / proff.arc / LTB.C < prev    next >
C/C++ Source or Header  |  1988-02-17  |  7KB  |  284 lines

  1. /*
  2.  * ltb.c - Lexical Table Builder
  3.  *
  4.  * Functional description:
  5.  *
  6.  *    This program builds a file containing the data
  7.  *    structures of a compile-time-initialised hash table. 
  8.  *    This hash table may later be used for lexical analysis,
  9.  *    where number of symbols to look up is sufficiently large
  10.  *    to avoid a run-time table initialization.
  11.  *    In order to guarantee the success of this setup, the 
  12.  *    hash routine, the lookup and install routines should be
  13.  *    the same between ltb and the lexical analysis.
  14.  *
  15.  * synopsis:
  16.  *
  17.  *    ltb <input file> [table name]
  18.  *
  19.  * input file format:
  20.  *
  21.  *    <token>  <value identifier> [flag value]
  22.  *
  23.  *    token:         string of alphanumeric characters to be 
  24.  *                   matched by the lexical analyser (no blanks).
  25.  *            these token strings are "installed" to a hash
  26.  *            table by ltb to avoid run-time overhead.
  27.  *    value 
  28.  *    identifier:    A constant name to be used internally by the
  29.  *            lexical analyser in place of the actual
  30.  *            token value. a "#define <indentifier> <value>"
  31.  *            is generated for each value identifier, where
  32.  *            value is an odd and unique integer constant. If
  33.  *            the value identifier is a `*' (star), then the
  34.  *            previous value is repeated. Thus:
  35.  *
  36.  *                   token   ident.   flag
  37.  *
  38.  *                sp    SP    1
  39.  *                space    *         { inherits SP  }
  40.  *                blank    *          { inherits SP  }
  41.  *                .    .    .
  42.  *                .    .    .
  43.  *
  44.  *    flag value:    An additional integer field to pass flags etc. to
  45.  *            the lexical analyser. If not specified, set to
  46.  *            0. token value field must be present for this field
  47.  *            to be obtained.
  48.  *
  49.  * outputs:
  50.  *
  51.  *    ltb generates two C include files:
  52.  *
  53.  *        [tablename].d:  compile time lexical constants (defines)
  54.  *        [tablename].h:    initialised hash table.
  55.  *
  56.  *    where [tablename] is the name of the hash table as specified
  57.  *    in the command line of ltb. If not specified, "lextab" is used
  58.  *    as a default.
  59.  *
  60.  * routines used by LTB:
  61.  *
  62.  *    hash, lookup and a modified version of install routines,
  63.  *    as defined in K&R, pp. 134 - 136.
  64.  *
  65.  * Application areas:
  66.  *
  67.  *    Lexical analysers for compilers, interpreters, spelling
  68.  *    checkers.
  69.  *
  70.  * Author:
  71.  *    Ozan S. Yigit
  72.  *    Dept. of Computer Science
  73.  *    York University
  74.  *
  75.  */
  76.  
  77. #define MAXLINE        80
  78. #define MAXSYM        80
  79.  
  80. #include <stdio.h>
  81. #include <ctype.h>
  82. #include "lookup.h"
  83.  
  84. static struct lexlist *hashtab[HASHMAX];
  85. static struct lexlist *defitab[HASHMAX];
  86.  
  87. char *tabnam;        /* table name */
  88.  
  89. main(argc,argv)
  90. int argc;
  91. char *argv[];
  92. {
  93.     FILE *fp;
  94.     char line[MAXLINE];
  95.     char sym[MAXSYM],def[MAXSYM];
  96.     register int val;
  97.     register int prev, *p;
  98.     register char *ptr;
  99.     int flag;
  100.     struct lexlist *np, *lexlook();
  101.  
  102.     if (argc <= 2) {
  103.         fprintf(stderr,"%s [-<base>] <symbol file> [tablename]",
  104.         argv[0]);
  105.         exit(1);
  106.     }
  107.  
  108.     if (*argv[1] == '-') {
  109.         val = atoi(argv[1]+1);    /* skip "-" and convert */
  110.         val = (val & 1) ? val : val+1;
  111.         p = argv[2];
  112.     }
  113.     else {
  114.         val = 1;
  115.         p = argv[1];
  116.     }
  117.  
  118.     if (argc < 3)
  119.         tabnam = "lextab";
  120.     else
  121.         tabnam = argv[argc-1];
  122.  
  123.     if ((fp = fopen(p,"r")) == NULL) {
  124.         fprintf(stderr,"%s:cannot open.\n",argv[1]);
  125.         exit(1);
  126.     }
  127.     else {
  128.         prev = val;
  129.         while (fgets(line,MAXLINE,fp) != NULL) {
  130.             if (*line != '!') {
  131.                 flag = 0; 
  132.                 def[0] = '\0';
  133.                 ptr = line;
  134.                 while (isspace(*ptr))
  135.                     ptr++;
  136.                 if (*ptr == '\0')
  137.                     continue;
  138.                 sscanf(line,"%s %s %d",sym,def,&flag);
  139.                 if (!(def[0] == '*' && def[1] == '\0')) {
  140.                     if ((np = lexlook(def,defitab)) == NULL) {
  141.                         /* value define  */
  142.                         lexinstal(def,val,0,defitab);
  143.                         prev = val;
  144.                         val += 2;
  145.                     }
  146.                     else
  147.                         prev = np->val;
  148.                 }
  149.                  /* lexical token */
  150.                 lexinstal(sym,prev,flag,hashtab);
  151.             }
  152.         }
  153.         defgen();
  154.         lexgen();
  155.     }
  156. }
  157. /*
  158.  * lexgen - print out the hash table in static form
  159.  *
  160.  */
  161. lexgen()
  162. {
  163.     register int i;
  164.     register struct lexlist *np;
  165.     char filebuf[12];
  166.     char *file;
  167.     FILE *op;
  168.  
  169.     file = filebuf;
  170.  
  171.     strncpy(file,tabnam,8);
  172.     strcat(file,".h");
  173.  
  174.     if ((op = fopen(file,"w")) == NULL) {
  175.         fprintf(stderr,"%s: cannot create.\n",file);
  176.         exit(1);
  177.     }
  178.  
  179.     fprintf(op,"#ifndef STRUC_DEFINED\n\n");
  180.     fprintf(op,"\/\*\t%s\t\*\/\n\n%s\n%s\n%s\n%s\n%s\n",file,
  181.     "struct _lex_h {     char     *__s;",
  182.     "              int      __v;",
  183.     "              int       __f;",
  184.     "        struct  _lex_h  *__l;",
  185.     "};");
  186.     fprintf(op,"\n#define STRUC_DEFINED\n#endif\n");
  187.  
  188.     /*
  189.              * generate the hash table entries.
  190.              * each entry is followed by the next entry in its
  191.              * chain.
  192.              * In the operating systems with memory paging, this
  193.              * should have the extra advantage of localized
  194.              * memory referances.
  195.              *
  196.      */
  197.  
  198.     for (i=0; i < HASHMAX; i++)
  199.         if ((np = hashtab[i]) != NULL)
  200.             prnode(np,op);
  201.     /*
  202.              * At last, we generate the pointer array (hashtable).
  203.              * this table should be assigned to lextable global
  204.              * variable before using with lexlook() or lexinstal().
  205.              * lextable is defined in lookup.h
  206.              *
  207.      */
  208.  
  209.     fprintf(op,"\n\n\/\*  Hash Table \*\/\n\n");
  210.     fprintf(op,"struct _lex_h *%s[%d] = {\n\t",tabnam,HASHMAX);
  211.     for (i=0; i < HASHMAX - 1; i++) {
  212.         np = hashtab[i];
  213.         if(np == NULL)
  214.             fprintf(op,"NULL,\t");
  215.         else
  216.             fprintf(op,"\&__%s,\t", np->name);
  217.         if (i % 4 == 0)
  218.             fprintf(op,"\n\t");
  219.     }
  220.     np = hashtab[i];
  221.     if (np == NULL)
  222.         fprintf(op,"NULL  };\n");
  223.     else
  224.         fprintf(op,"\&__%s   };\n", np->name);
  225.  
  226.     fclose(op);
  227. }
  228.  
  229. /*
  230.  * prnode - print the current node. This routine is 
  231.  *        recursive such that printing starts from
  232.  *        the end of the given list
  233.  *
  234.  */
  235. prnode(np,op)
  236. register struct
  237. lexlist *np;
  238. FILE *op;
  239. {
  240.     if (np->link != NULL)
  241.         prnode(np->link,op);
  242.     fprintf(op,"struct\n_lex_h __%s = {  ",
  243.     np->name);
  244.     fprintf(op,"\"%s\",\n              %6d,%6d,",
  245.     np->name,
  246.     np->val,
  247.     np->flag);
  248.     if (np->link != NULL)
  249.         fprintf(op,"\&__%s };\n",
  250.         (np->link)->name);
  251.     else
  252.         fprintf(op,"NULL };\n");
  253. }    
  254.  
  255. /*
  256.  * defgen - generate a file containing the lexical
  257.  *        constants to be equated to lexical symbols
  258.  */
  259. defgen()
  260. {
  261.     register int i;
  262.     register struct lexlist *np;
  263.     char *file;
  264.     char filebuf[12];
  265.     FILE *op;
  266.  
  267.     file = filebuf;
  268.     strncpy(file,tabnam,8);
  269.     strcat(file,".d");
  270.  
  271.     if ((op = fopen(file,"w")) == NULL) {
  272.         fprintf(stderr,"%s: cannot create.\n",file);
  273.         exit(1);
  274.     }
  275.     for (i=0; i < HASHMAX; i++) {
  276.         for (np = defitab[i]; np != NULL; np = np->link)
  277.             fprintf(op,"\#define  %s\t%d\n",
  278.             np->name,
  279.             np->val);
  280.     }
  281.     fclose(op);
  282. }
  283.  
  284.